﻿using SPWebShell.entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Web.Services.Protocols;

namespace SPWebShell.cmdlet
{
    /// <summary>
    /// Gets a listing of all lists at the specified URL. (recursive option also provided)
    /// </summary>
    [Cmdlet(VerbsCommon.Get, "SPLists")]
    public class GetSPLists : CmdLetBase
    {
        string _urlContainerSite;
        ISPRepository _repos;
        public GetSPLists()
        {
            this.Recurse = false;
        }
        
        [Parameter(Mandatory = true, HelpMessage="The absolute URL to the SharePoint site collection. e.g. http://server/sites/SiteA/")]
        [ValidateNotNullOrEmpty]
        public string Url { get; set; }

        [Parameter(Mandatory = false, HelpMessage = "When set to True, all descendant sites are obtained. Default is False" )]
        [Alias("recursive")]
        public bool Recurse { get; set; }

        private SPWeb[] GetAllWebs()
        {
                List<SPWeb> masterlist = new List<SPWeb>();
                Action<string> fnRecurse = null;
                fnRecurse=delegate(string url)
                {
                    VerboseLogger(string.Format("Enumerating websites under:{0}", url));
                    SPWeb[] webs = _repos.GetWebs(url);
                    foreach (SPWeb web in webs)
                    {
                        if (!web.Url.EndsWith("/")) web.Url = web.Url + "/";
                        masterlist.Add(web);
                        fnRecurse(web.Url);
                    }
                };
                masterlist.Add(new SPWeb { Title = "", Url = this._urlContainerSite });
                if (this.Recurse)
                {
                    fnRecurse(_urlContainerSite);
                }
                else
                {
                    //SPWeb[] webs = _repos.GetWebs(this._urlContainerSite);
                    //foreach (SPWeb web in webs)
                    //{
                    //    masterlist.Add(web);
                    //}
                }
            return masterlist.ToArray();    
        }
        protected override void ProcessRecord()
        {
            try
            {
                VerboseLogger("Start time: " + DateTime.Now.ToString());
                VerboseLogger (string.Format("Url:{0},Recurse:{1}",this.Url,this.Recurse) );
                _repos= base.SPRepos;
                VerboseLogger("Resolving container site from supplied URL");
                VerboseLogger("Value of dump:" + this.Dump);
                string dumpFilepath="";
                if (this.Dump)
                {
                    if (string.IsNullOrEmpty(File))
                    {
                        ErrorLogger("Expected path to file (property File) where the raw XML contents will be written. ");
                    }
                    else
                    {
                        dumpFilepath= this.GetFullPathToFile(this.File);
                        VerboseLogger("Full path to file:" + dumpFilepath);
                        VerboseLogger("Trying to delete file:" + dumpFilepath);
                        if (System.IO.File.Exists(dumpFilepath))
                        {
                            System.IO.File.Delete(dumpFilepath);
                        }
                    }
                }                 
                _urlContainerSite = _repos.GetContainerWebFromDocLibUrl(this.Url);
                VerboseLogger("Container url:" + _urlContainerSite);
                SPWeb[] allwebs = this.GetAllWebs();
                VerboseLogger(string.Format("Got a list of all subsites, Count={0}",allwebs.Count()) );
                List<SPList> alllists = new List<SPList>();
                foreach (SPWeb web in allwebs)
                {
                    VerboseLogger(string.Format("Enumerating lists in site:{0}",web.Url));
                    SPList[] listsinthissite = _repos.GetLists(web.Url);
                    VerboseLogger(string.Format("Got a list of all lists,Count:{0}",listsinthissite.Count()));
                    foreach(SPList list in listsinthissite)
                    {
                        list.NameValues.Add("Url", web.Url);
                    }
                    alllists.AddRange(listsinthissite);
                }
                VerboseLogger("Enumerating through all lists");
                string[] properties = null;
                if ( (this.Properties != null) && (this.Properties.Length > 0))
                {
                    properties = (from p in this.Properties select p.Trim()).ToArray();
                }
                foreach (SPList list in alllists)
                {
                    VerboseLogger("List:" + list.Title);
                    PSObject o1 = new PSObject();
                    o1.Members.Add(new PSNoteProperty("ID", list.ID));
                    o1.Members.Add(new PSNoteProperty("Name", list.Title));
                    o1.Members.Add(new PSNoteProperty("ItemCount", list.ItemCount));
                    o1.Members.Add(new PSNoteProperty("DefaultViewUrl", list.DefaultViewUrl));
                    if (this.Dump)
                    {
                        VerboseLogger("Dumping to file");
                        System.IO.File.AppendAllText(dumpFilepath, list.ToString());
                        System.IO.File.AppendAllText(dumpFilepath, "\r\n");
                        VerboseLogger(string.Format("Contents of the XML was written to file:{0}", this.File));
                    }
                    string urlSite=list.NameValues["Url"];
                    o1.Members.Add(new PSNoteProperty("Url", urlSite));
                    if ((properties!=null) && (properties.Length > 0))
                    {
                        foreach (string property in properties)
                        {
                            string value = list.NameValues[property];
                            PSNoteProperty dynamicprop = new PSNoteProperty(property, value);
                            o1.Members.Add(dynamicprop);
                        }
                    }
                    WriteObject(o1);
                }
                base.ProcessRecord();
            }
            catch (SoapException ex)
            {
                string message = ex.Detail.OuterXml;
                throw new Exception(message, ex);
            }
            finally
            {
                WriteVerbose("End time: " + DateTime.Now.ToString());
            }
        }
        [Parameter(Mandatory = false, HelpMessage = "When set to True the complete List schema XML will be saved to a file")]
        public bool Dump { get; set; }

        [Parameter(Mandatory = false, HelpMessage = "The name of the file where the List schema will be optionally written to when Dump=True")]
        public string File { get; set; }

        [Parameter(Mandatory = false, HelpMessage = "A comma separated list of fields to display in the output. Use the Dump option to view all fields in the XML. ID, ItemCount,EnableVersioning")]
        [Alias("Property")]
        public string[] Properties { get; set; }


    }
}
